return ret;
}
-static inline int do_xen_blkmsg(privcmd_blkmsg_t *blkmsg)
-{
- return do_privcmd(IOCTL_PRIVCMD_BLKMSG, (unsigned long)blkmsg);
-}
-
static inline int do_xen_hypercall(privcmd_hypercall_t *hypercall)
{
return do_privcmd(IOCTL_PRIVCMD_HYPERCALL, (unsigned long)hypercall);
*/
domain = atoi(argv[2]);
device = atoi(argv[3]);
- /* XXX SMH: hack -- generate device name by addition ptn number */
+ /* XXX SMH: hack -- generate device name by addition ptn number */
vdevice = device + atoi(argv[6]);
op.cmd = BLOCK_IO_OP_VBD_CREATE;
op.u.create_info.domain = domain;
op.u.create_info.vdevice = vdevice;
+ op.u.create_info.mode = 0;
+ if ( strchr(argv[1], 'r') )
+ op.u.create_info.mode |= VBD_MODE_R;
+ if ( strchr(argv[1], 'w') )
+ op.u.create_info.mode |= VBD_MODE_W;
ret = do_block_io_op(&op);
op.u.add_info.extent.device = device;
op.u.add_info.extent.start_sector = atol(argv[4]);
op.u.add_info.extent.nr_sectors = atol(argv[5]);
- op.u.add_info.extent.mode = 0;
- if ( strchr(argv[1], 'r') )
- op.u.add_info.extent.mode |= PHYSDISK_MODE_R;
- if ( strchr(argv[1], 'w') )
- op.u.add_info.extent.mode |= PHYSDISK_MODE_W;
-
ret = do_block_io_op(&op);
if(ret < 0) {
new_vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL);
new_vbd->vdevice = create_info->vdevice;
+ new_vbd->mode = create_info->mode;
new_vbd->extents = (xen_extent_le_t *)NULL;
new_vbd->next = (vbd_t *)NULL;
xele->extent.device = add_info->extent.device;
xele->extent.start_sector = add_info->extent.start_sector;
xele->extent.nr_sectors = add_info->extent.nr_sectors;
- xele->extent.mode = add_info->extent.mode;
xele->next = (xen_extent_le_t *)NULL;
if(!v->extents) {
return -ENODEV;
}
+ if(operation == READ && !VBD_CAN_READ(v))
+ return -EACCES;
+
+ if(operation == WRITE && !VBD_CAN_WRITE(v))
+ return -EACCES;
+
+
/* Now iterate through the list of xen_extents, working out which
should be used to perform the translation. */
sec = pseg->sector_number;
/* we've got a match! XXX SMH: should deal with
situation where we span multiple xe's */
- if(operation == READ && !(x->extent.mode & PHYSDISK_MODE_R))
- return -EACCES;
-
- if(operation == WRITE && !(x->extent.mode & PHYSDISK_MODE_W))
- return -EACCES;
-
pseg->dev = x->extent.device;
pseg->sector_number += x->extent.start_sector;
for(i = 0; i < VBD_HTAB_SZ; i++) {
for(v = p->vbdtab[i]; v; v = v->next) {
xdi->disks[xdi->count].device = v->vdevice;
- xdi->disks[xdi->count].type = XD_TYPE_DISK; // always :-)
+ xdi->disks[xdi->count].info = XD_FLAG_VIRT | XD_TYPE_DISK;
+
+ /* XXX SMH: and now set XD_FLAG_RO if necessary */
+
xdi->disks[xdi->count].capacity = 0;
for(x = v->extents; x; x = x->next)
xdi->disks[xdi->count].capacity += x->extent.nr_sectors;
capacity = current_capacity(drive);
xdi->disks[xdi->count].device = device;
- xdi->disks[xdi->count].type = type;
+ xdi->disks[xdi->count].info = type;
xdi->disks[xdi->count].capacity = capacity;
xdi->count++;
/* XXX SMH: if make generic, need to properly determine 'type' */
xdi->disks[xdi->count].device = device;
- xdi->disks[xdi->count].type = XD_TYPE_DISK;
+ xdi->disks[xdi->count].info = XD_TYPE_DISK;
xdi->disks[xdi->count].capacity = capacity;
xdi->count++;
#define XEN_BLOCK_SPECIAL 4
#define XEN_BLOCK_PROBE 5 /* get config from hypervisor */
#define XEN_BLOCK_DEBUG 6 /* debug */
-#define XEN_BLOCK_VBD_CREATE 7 /* create vbd */
-#define XEN_BLOCK_VBD_DELETE 8 /* delete vbd */
- /* XXX SMH: was 'probe vbd' */
-#define XEN_BLOCK_PHYSDEV_GRANT 10 /* grant access to range of disk blocks */
-#define XEN_BLOCK_PHYSDEV_PROBE 11 /* probe for a domain's physdev accesses */
- /* XXX SMH: was 'probe vbd all' */
/* NB. Ring size must be small enough for sizeof(blk_ring_t) <= PAGE_SIZE. */
#define BLK_RING_SIZE 64
} blk_ring_t;
/*
- *
- * physical disk (xhd) info, used by XEN_BLOCK_PROBE
- *
- */
-
-#define XEN_MAX_DISK_COUNT 100
+ * Information about the real and virtual disks we have; used during
+ * guest device probing.
+ */
+#define XEN_MAX_DISK_COUNT 64
/* XXX SMH: below types chosen to align with ide_xxx types in ide.h */
#define XD_TYPE_FLOPPY 0x00
#define XD_TYPE_OPTICAL 0x07
#define XD_TYPE_DISK 0x20
+#define XD_TYPE_MASK 0x3F
+#define XD_TYPE(_x) ((_x) & XD_TYPE_MASK)
+
+/* The top two bits of the type field encode various flags */
+#define XD_FLAG_RO 0x40
+#define XD_FLAG_VIRT 0x80
+#define XD_READONLY(_x) ((_x) & XD_FLAG_RO)
+#define XD_VIRTUAL(_x) ((_x) & XF_FLAG_VIRT)
+
typedef struct xen_disk
{
- unsigned short device; /* device number (see top of file) */
- unsigned short type; /* device type, i.e. disk, cdrom, etc */
+ unsigned short device; /* device number (opaque 16 bit val) */
+ unsigned short info; /* device type and flags */
unsigned long capacity; /* size in terms of #512 byte sectors */
} xen_disk_t;
#define __HYP_IFS_VBD_H__
-#define PHYSDISK_MODE_R 1
-#define PHYSDISK_MODE_W 2
-
-#if 0
-typedef struct xp_disk
-{
- int mode; /* 0 -> revoke existing access, otherwise bitmask of
- PHYSDISK_MODE_? constants */
- int domain;
- unsigned short device; /* XENDEV_??? + idx */
- unsigned short partition; /* partition number */
- unsigned long start_sect;
- unsigned long n_sectors;
-} xp_disk_t;
-
-#define PHYSDISK_MAX_ACES_PER_REQUEST 254 /* Make it fit in one page */
-typedef struct {
- int n_aces;
- int domain;
- int start_ind;
- struct {
- unsigned short device; /* XENDEV_??? + idx */
- unsigned short partition; /* partition number */
- unsigned long start_sect;
- unsigned long n_sectors;
- unsigned mode;
- } entries[PHYSDISK_MAX_ACES_PER_REQUEST];
-} physdisk_probebuf_t;
-#endif
-
-
-/* Block I/O trap operations and associated structures.
+/*
+ * Block I/O trap operations and associated structures.
*/
#define BLOCK_IO_OP_SIGNAL 0 /* let xen know we have work to do */
#define BLOCK_IO_OP_RESET 1 /* reset ring indexes on quiescent i/f */
-#define BLOCK_IO_OP_RING_ADDRESS 2 /* returns machine address of I/O ring */
+#define BLOCK_IO_OP_RING_ADDRESS 2 /* returns machine address of I/O ring */
#define BLOCK_IO_OP_VBD_CREATE 3 /* create a new VBD for a given domain */
#define BLOCK_IO_OP_VBD_ADD 4 /* add an extent to a given VBD */
#define BLOCK_IO_OP_VBD_REMOVE 5 /* remove an extent from a given VBD */
typedef struct _xen_extent {
u16 device;
+ u16 unused; // pad
ulong start_sector;
ulong nr_sectors;
- u16 mode;
} xen_extent_t;
+
+
+#define VBD_MODE_R 0x1
+#define VBD_MODE_W 0x2
+
+#define VBD_CAN_READ(_v) ((_v)->mode & VBD_MODE_R)
+#define VBD_CAN_WRITE(_v) ((_v)->mode & VBD_MODE_R)
+
typedef struct _vbd_create {
unsigned domain;
u16 vdevice;
+ u16 mode;
} vbd_create_t;
-
typedef struct _vbd_add {
unsigned domain;
u16 vdevice;
*/
typedef struct _vbd {
unsigned short vdevice; // what the domain refers to this vbd as
+ unsigned short mode; // VBD_MODE_{READONLY,READWRITE}
xen_extent_le_t *extents; // list of xen_extents making up this vbd
struct _vbd *next; // for chaining in the hash table
} vbd_t;
#define VBD_HTAB_SZ 16 // no. of entries in the vbd hash table.
-void xen_vbd_initialize(void);
-void xen_refresh_vbd_list (struct task_struct *p);
long vbd_create(vbd_create_t *create_info);
long vbd_add(vbd_add_t *add_info);
long vbd_remove(vbd_remove_t *remove_info);
long vbd_delete(vbd_delete_t *delete_info);
-/* Describes a physical disk extent (part of a block io request) */
+
+/* Describes a [partial] disk extent (part of a block io request) */
typedef struct {
unsigned short dev;
unsigned short nr_sects;
struct task_struct *p, int operation);
-#if 0
-void destroy_physdisk_aces(struct task_struct *p);
-
-int xen_physdisk_grant(xp_disk_t *);
-int xen_physdisk_probe(struct task_struct *requesting_task,
- physdisk_probebuf_t *);
-int xen_physdisk_access_okay(phys_seg_t *pseg, struct task_struct *p,
- int operation);
-#endif
-
-
-#endif /* PHYSDISK_ACES__ */
+#endif /* __VBD_H__ */
return 0;
}
+/* check media change: should probably do something here in some cases :-) */
int xenolinux_block_check(kdev_t dev)
{
DPRINTK("xenolinux_block_check\n");
switch ( operation )
{
-// case XEN_BLOCK_PHYSDEV_GRANT:
-// case XEN_BLOCK_PHYSDEV_PROBE:
case XEN_BLOCK_PROBE:
if ( RING_PLUGGED ) return 1;
sector_number = 0;
}
break;
- case XEN_BLOCK_VBD_CREATE:
- case XEN_BLOCK_VBD_DELETE:
- case XEN_BLOCK_PHYSDEV_GRANT:
- case XEN_BLOCK_PHYSDEV_PROBE:
- printk(KERN_ALERT "response for bogus operation %d\n",
- bret->operation);
case XEN_BLOCK_PROBE:
xlblk_control_msg_pending = bret->status;
break;
int __init xlvbd_init(xen_disk_info_t *xdi)
{
int i, result, nminors;
- struct gendisk *gd;
+ struct gendisk *gd = NULL;
kdev_t device;
unsigned short major, minor, real_minor;
bool is_ide, is_scsi;
majors[major] = 1;
}
+ if(XD_READONLY(xdi->disks[i].info))
+ set_device_ro(device, 1);
+
if(real_minor) {
/* Need to skankily setup 'partition' information */
} else {
/* Some final fix-ups depending on the device type */
- switch (xdi->disks[i].type)
+ switch (XD_TYPE(xdi->disks[i].info))
{
+
case XD_TYPE_CDROM:
- set_device_ro(device, 1);
-
case XD_TYPE_FLOPPY:
case XD_TYPE_TAPE:
gd->flags[0] = GENHD_FL_REMOVABLE;
printk(KERN_ALERT
"Skipping partition check on %s /dev/%s\n",
- xdi->disks[i].type==XD_TYPE_CDROM ? "cdrom" :
- (xdi->disks[i].type==XD_TYPE_TAPE ? "tape" :
+ XD_TYPE(xdi->disks[i].info)==XD_TYPE_CDROM ? "cdrom" :
+ (XD_TYPE(xdi->disks[i].info)==XD_TYPE_TAPE ? "tape" :
"floppy"), disk_name(gd, MINOR(device), buf));
break;
-
+
case XD_TYPE_DISK:
register_disk(gd, device, gd->nr_real, &xlvbd_block_fops,
xdi->disks[i].capacity);
break;
default:
- printk(KERN_ALERT "XenoLinux: unknown ide device type %d\n",
- xdi->disks[i].type);
+ printk(KERN_ALERT "XenoLinux: unknown device type %d\n",
+ XD_TYPE(xdi->disks[i].info));
break;
}
void xlvbd_cleanup(void)
{
-#if 0
- if ( xlvbd_gendisk == NULL ) return;
-
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(XLVIRT_MAJOR));
+ bool is_ide, is_scsi;
+ struct gendisk *gd;
+ char *major_name;
+ int major;
- xlvbd_gendisk = NULL;
+ for(major = 0; major < XLVBD_MAX_MAJORS; major++) {
- read_ahead[XLVIRT_MAJOR] = 0;
+ if(!(gd = xlvbd_gendisk[major]))
+ continue;
- if ( blksize_size[XLVIRT_MAJOR] != NULL )
- {
- kfree(blksize_size[XLVIRT_MAJOR]);
- blksize_size[XLVIRT_MAJOR] = NULL;
- }
+ is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */
+ is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */
+
+ blk_cleanup_queue(BLK_DEFAULT_QUEUE(major));
+
+ if(is_ide) {
+ major_name = XLIDE_MAJOR_NAME;
+ } else if(is_scsi) {
+ major_name = XLSCSI_MAJOR_NAME;
+ } else {
+ major_name = XLVBD_MAJOR_NAME;
+ }
+
+ if (unregister_blkdev(major, major_name) != 0)
+ printk(KERN_ALERT "XenoLinux Virtual Block Device Driver:"
+ "major device %04x uninstalled w/ errors\n", major);
- if ( hardsect_size[XLVIRT_MAJOR] != NULL )
- {
- kfree(hardsect_size[XLVIRT_MAJOR]);
- hardsect_size[XLVIRT_MAJOR] = NULL;
- }
-
- if ( max_sectors[XLVIRT_MAJOR] != NULL )
- {
- kfree(max_sectors[XLVIRT_MAJOR]);
- max_sectors[XLVIRT_MAJOR] = NULL;
- }
-
- if ( unregister_blkdev(XLVIRT_MAJOR, XLVIRT_MAJOR_NAME) != 0 )
- {
- printk(KERN_ALERT
- "XenoLinux Virtual Block Device Driver"
- " uninstalled w/ errs\n");
}
-#endif
- printk(KERN_ALERT "xlvbd_cleanup: not implemented XXX FIXME SMH\n");
+
+ return;
}